package battleofthejavasea;

import com.sun.j3d.utils.universe.SimpleUniverse;
import java.io.FileNotFoundException;
import java.io.Serializable;

/**
 *
 * @author Murata, Saito, Santana
 * Classe que grava o posicionamento dos barcos dos jogadores em memória.
 * Estes objetos serão sincronizados com o servidor.
 * Player 1 define o jogador local.
 * Player 2 define o jogador remoto.
 */
public class BTJSGameLogic implements Serializable {
        public BTJSGameLogic(){
        this.player1Boats = new BTJS_DTOPlayerBoats();
        this.player2Boats = new BTJS_DTOPlayerBoats();

    }

    private BTJS_DTOPlayerBoats player1Boats;
    private BTJS_DTOPlayerBoats player2Boats;

    //gets/sets
    public BTJS_DTOPlayerBoats getPlayer1BoatsCoords(){
        return this.player1Boats;
    }
    public void setPlayer1Boats(BTJS_DTOPlayerBoats player1Boats){
        this.player1Boats = player1Boats;
    }
    public BTJS_DTOPlayerBoats  getPlayer2BoatsCoords(){
        return this.player2Boats;
    }
    public void setPlayer2Boats(BTJS_DTOPlayerBoats  player2Boats){
        this.player2Boats = player2Boats;
    }


    //Verifica qual tipo de barco está sendo adicionado e se ele foi rotacionado.
    //Adiciona todas as coordenadas para o objeto de posicionamento.
    public void addBoatCoordinates(String boatType, String rowStart, int colStart, boolean rotate) {

        if(boatType.equals("crusador.obj")){
            if(rotate){
                this.player1Boats.add(new BTJS_DTOBoatUnitPosition(rowStart, colStart));
                this.player1Boats.add(new BTJS_DTOBoatUnitPosition(rowStart, colStart+1));
            }
            else{

                this.player1Boats.add(new BTJS_DTOBoatUnitPosition(rowStart, colStart));
                this.player1Boats.add(new BTJS_DTOBoatUnitPosition(fetchNextRow(rowStart), colStart));
            }
        }

        else if(boatType.equals("submarine.obj")){
            this.player1Boats.add(new BTJS_DTOBoatUnitPosition(rowStart, colStart));
        }

        else if(boatType.equals("encouracado.obj")){
            if(rotate){
                this.player1Boats.add(new BTJS_DTOBoatUnitPosition(rowStart, colStart));
                this.player1Boats.add(new BTJS_DTOBoatUnitPosition(rowStart, colStart+1));
                this.player1Boats.add(new BTJS_DTOBoatUnitPosition(rowStart, colStart+2));
            }
            else{
                this.player1Boats.add(new BTJS_DTOBoatUnitPosition(rowStart, colStart));
                this.player1Boats.add(new BTJS_DTOBoatUnitPosition(fetchNextRow(rowStart), colStart));
                this.player1Boats.add(new BTJS_DTOBoatUnitPosition(fetchNextRow(fetchNextRow(rowStart)), colStart));
            }

        }

        else if (boatType.equals("portaAviao.obj")){
            if(rotate){
                this.player1Boats.add(new BTJS_DTOBoatUnitPosition(rowStart, colStart));
                this.player1Boats.add(new BTJS_DTOBoatUnitPosition(rowStart, colStart+1));
                this.player1Boats.add(new BTJS_DTOBoatUnitPosition(rowStart, colStart+2));
                this.player1Boats.add(new BTJS_DTOBoatUnitPosition(rowStart, colStart+3));
            }
            else{
                this.player1Boats.add(new BTJS_DTOBoatUnitPosition(rowStart, colStart));
                this.player1Boats.add(new BTJS_DTOBoatUnitPosition(fetchNextRow(rowStart), colStart));
                this.player1Boats.add(new BTJS_DTOBoatUnitPosition(fetchNextRow(fetchNextRow(rowStart)), colStart));
                this.player1Boats.add(new BTJS_DTOBoatUnitPosition(fetchNextRow(fetchNextRow(fetchNextRow(rowStart))), colStart));
            }
        }


    }

    //Classe auxiliar: determina a próxima linha.
    //i.e. fetchNextRow("a") >> output > "b"
    public String fetchNextRow(String rowStart) {
        if(rowStart.toLowerCase().equals("a"))
            return "b";
        else if(rowStart.toLowerCase().equals("b"))
            return "c";
        else if(rowStart.toLowerCase().equals("c"))
            return "d";
        else if(rowStart.toLowerCase().equals("d"))
            return "e";
        else if(rowStart.toLowerCase().equals("e"))
            return "f";
        else if(rowStart.toLowerCase().equals("f"))
            return "g";
        else if(rowStart.toLowerCase().equals("g"))
            return "h";
        else if(rowStart.toLowerCase().equals("h"))
            return "i";
        else if(rowStart.toLowerCase().equals("i"))
            return "j";
        else
            return "";
    }


    //Método que indica onde o usuário está atirando.
    public void shootCoordinate(String shotRow, int shotCol, SimpleUniverse simpleUniverse) throws FileNotFoundException{
        hitCheckDraw(shotRow, shotCol, this.player2Boats, simpleUniverse);
    }

    //Verifica se um dos lados obteve vitória.
    public BTJS_DTOPlayerWinner checkGameEnd(BTJS_DTOPlayerWinner btjsPW ){

        int localPlayerBoatCellsToHit = 0;
        int remotePlayerBoatCellsToHit = 0;

        for(BTJS_DTOBoatUnitPosition btjsBUP : player1Boats.getBoatPositions()){
            //Ainda há células sem acerto
            if(!btjsBUP.hasBeenShot)
                localPlayerBoatCellsToHit++;
              
        }

        for(BTJS_DTOBoatUnitPosition btjsBUP : player2Boats.getBoatPositions()){
            //Ainda há células sem acerto
            if(!btjsBUP.hasBeenShot)
               remotePlayerBoatCellsToHit++;
        }

        //Verificação de vitória pelo jogador local
        if(localPlayerBoatCellsToHit == 0)
            btjsPW.setIsRemotePlayerWinner(true);
        else 
            btjsPW.setIsRemotePlayerWinner(false);
        
        //Verificação de vitória pelo jogador remoto
        if(remotePlayerBoatCellsToHit == 0)
            btjsPW.setIsLocalPlayerWinner(true);
        else
            btjsPW.setIsLocalPlayerWinner(false);
        
        return btjsPW;
    }

    //Verifica se o tiro atingiu algo. Caso positivo, mostra uma esfera verde na posição e marca a posicao como atingida.
    //Caso contrário, mostra o x vermelho.
    public void hitCheckDraw(String shotRow, int shotCol, BTJS_DTOPlayerBoats positions, SimpleUniverse simpleUniverse) throws FileNotFoundException{
        //Objeto que renderiza símbolos do jogo na cena
        BTJSGameSymbols btjsGameSymbols = new BTJSGameSymbols();
        //Interpretador de posicionamento para a cena 3d
        BTJSPositionInterpreter btjsPositionInterpreter = new BTJSPositionInterpreter();

        boolean positiveHit = false;

        //Itera por todas as posições do inimigo
        for(int i = 0; i < 26; i++){

            if(positions.getBoatPositions()[i].row.equals(shotRow.toLowerCase()) && positions.getBoatPositions()[i].column == shotCol)
            {
                //Há algo aqui!
                //Marca hit no meu próprio tabuleiro, que já atualiza a informação via sockets
                player1Boats.getBoatPositions()[i].hasBeenShot = true;
                //Adiciona esfera verde de acerto no painel de tiros.
                simpleUniverse.addBranchGraph(btjsGameSymbols.bullsEye(btjsPositionInterpreter.getRowValueShot(shotRow), btjsPositionInterpreter.getColumnValue(shotCol)));
                positiveHit = true;
            }

        }


        //Marca a posição do tiro inimigo.
        //A posição dos tiros são sincronizadas em tempo real pelas Threads de conectividade.
        player1Boats.addEnemyShots(new BTJS_DTOBoatUnitPosition(shotRow, shotCol, positiveHit));


        //Se não acertou, adiciona X vermelho na posição escolhida.
        if(!positiveHit)
                simpleUniverse.addBranchGraph(btjsGameSymbols.missShot(btjsPositionInterpreter.getRowValueShot(shotRow), btjsPositionInterpreter.getColumnValue(shotCol)));
    }

    //Método utilizado para validar posições válidas para a sonda
    public boolean checkSondaPosition(float row, float col){
        if(row > 2.5f || col > 2.5f)
            return false;
        else
            return true;
    }


    //Método utilizado para verificar sobreposições de peças e posições válidas de barcos no tabuleiro.
    public boolean checkPosition(String boatType, float row, float col, String rowValue, int colValue, boolean rotated){

        boolean positionOk = true;

        //Primeiramente verifica o tipo de barco e se é uma posição válida
        if(boatType.equals("crusador"))
        {
            //Posições que estouram o limite do tabuleiro para este tipo de barco.
            if(!rotated){
                if(row > 3.5f)
                    positionOk = false;
            }
            else{
                if(col > 3.5f)
                    positionOk = false;
            }

            //Verifica se não há problema de colisão em células
            for(BTJS_DTOBoatUnitPosition pos : this.player1Boats.getBoatPositions()) {
                if(pos != null){
                    if(rotated){
                        if(pos.row.equals(rowValue) && pos.column == colValue)
                            positionOk = false;
                        else if(pos.row.equals(rowValue) && pos.column == colValue+1)
                            positionOk = false;
                    }
                    else{
                        if(pos.row.equals(rowValue) && pos.column == colValue)
                            positionOk = false;
                        else if(pos.row.equals(fetchNextRow(rowValue)) && pos.column == colValue)
                            positionOk = false;
                    }
                }
            }

        }
        else if(boatType.equals("submarine")){
            //Apenas precisa validar posição
            //Verifica se não há problema de colisão em células
            for(BTJS_DTOBoatUnitPosition pos : this.player1Boats.getBoatPositions()) {
                if(pos != null){
                    if(rotated){
                        if(pos.row.equals(rowValue) && pos.column == colValue)
                            positionOk = false;
                    }
                    else{
                        if(pos.row.equals(rowValue) && pos.column == colValue)
                            positionOk = false;
                    }
                }
            }
        }
        else if(boatType.equals("encouracado")){
            //Posições que estouram o limite do tabuleiro para este tipo de barco.
            if(!rotated){
                if(row > 2.5f)
                    positionOk = false;
            }
            else{
                if(col > 2.5f)
                    positionOk = false;
            }

            //Verifica se não há problema de colisão em células
            for(BTJS_DTOBoatUnitPosition pos : this.player1Boats.getBoatPositions()) {
                if(pos != null){
                    if(rotated){
                        if(pos.row.equals(rowValue) && pos.column == colValue)
                            positionOk = false;
                        else if(pos.row.equals(rowValue) && pos.column == colValue+1)
                            positionOk = false;
                        else if(pos.row.equals(rowValue) && pos.column == colValue+2)
                            positionOk = false;
                    }
                    else{
                        if(pos.row.equals(rowValue) && pos.column == colValue)
                            positionOk = false;
                        else if(pos.row.equals(fetchNextRow(rowValue)) && pos.column == colValue)
                            positionOk = false;
                        else if(pos.row.equals(fetchNextRow(fetchNextRow(rowValue))) && pos.column == colValue)
                            positionOk = false;
                    }
                }
            }
        }
        else if(boatType.equals("portaaviao")){
            //Posições que estouram o limite do tabuleiro para este tipo de barco.
            if(!rotated){
                if(row > 1.5f)
                    positionOk = false;
            }
            else{
                if(col > 1.5f)
                    positionOk = false;
            }

            //Verifica se não há problema de colisão em células
            for(BTJS_DTOBoatUnitPosition pos : this.player1Boats.getBoatPositions()) {
                if(pos != null){
                    if(rotated){
                        if(pos.row.equals(rowValue) && pos.column == colValue)
                            positionOk = false;
                        else if(pos.row.equals(rowValue) && pos.column == colValue+1)
                            positionOk = false;
                        else if(pos.row.equals(rowValue) && pos.column == colValue+2)
                            positionOk = false;
                        else if(pos.row.equals(rowValue) && pos.column == colValue+3)
                            positionOk = false;
                    }
                    else{
                        if(pos.row.equals(rowValue) && pos.column == colValue)
                            positionOk = false;
                        else if(pos.row.equals(fetchNextRow(rowValue)) && pos.column == colValue)
                            positionOk = false;
                        else if(pos.row.equals(fetchNextRow(fetchNextRow(rowValue))) && pos.column == colValue)
                            positionOk = false;
                        else if(pos.row.equals(fetchNextRow(fetchNextRow(fetchNextRow(rowValue)))) && pos.column == colValue)
                            positionOk = false;
                    }
                }
            }
        }

        return positionOk;
    }



}


    

